<?php

namespace Yousheng\Ku;

use Illuminate\Support\Str;
use LogicException;
use Stringable;

/**
 * Database Table Object.
 */
final class Table implements Stringable
{
    private ?string $databaseName;
    /**
     * Table name.
     */
    private string $name;

    /**
     * Column array.
     *
     * @var array<\Yousheng\Ku\Column>
     */
    private array $columns = [];

    /**
     * Foreign key array.
     *
     * @var array<\Yousheng\Ku\ForeignKey>
     */
    private array $foreignKeys = [];

    private array $indexes = [];

    /**
     * Constructor.
     *
     * @param  string  $name  Table name
     * @param  array<\Yousheng\Ku\Table>|null  $columns  Column array[Table]
     * @param  array<\Yousheng\Ku\ForeignKey>|null  $foreignKeys  Foreign key array
     */
    public function __construct(string $name, ?array $columns = [], ?array $foreignKeys = [], ?array $indexes = [], ?string $databaseName)
    {
        assert(! empty($columns), new LogicException('Columns must not be empty'));

        $this->name = $name;

        $this->columns = $columns;

        $this->foreignKeys = $foreignKeys;
        $this->indexes = $indexes;
        $this->databaseName = $databaseName;
    }

    /**
     * Get column array.
     *
     * @return array<\Yousheng\Ku\Column> The method returns `\Yousheng\Ku\Column` array
     */
    public function getColumns(): array
    {
        return $this->columns;
    }
    public function getDatabaseName(): string
    {
        return $this->databaseName;
    }

    /**
     * Get key array.
     *
     * @return array<\Yousheng\Ku\ForeignKey> The method returns `\Yousheng\Ku\Key` array
     */
    public function getForeignKeys(): array
    {
        return $this->foreignKeys;
    }

    /**
     * 读取索引
     *
     * @return array<\Yousheng\Ku\Index> The method returns `\Yousheng\Ku\Index` array
     */
    public function getIndexes(): array
    {
        return $this->indexes;
    }

    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Get the model name from table name.
     *
     * @return string The method returns the ModelName
     *
     * @example echo (new Table('users'))->model();
     * //=> User
     */
    public function model(?string $suffix = null): string
    {
        return Str::studly($this->name) . $suffix;
    }

    /**
     * Get the Nova resource name from table name.
     *
     * @return string The method returns the NovaResourceName
     *
     * @example echo (new Table('users'))->nova();
     * //=> User
     */
    public function nova(?string $suffix = null): string
    {
        return $this->model($suffix);
    }

    /**
     * Get the title for Nova resource name from table name.
     *
     * @return string The method returns the title for NovaResource name
     *
     * @example echo (new Table('users'))->title();
     * //=> User
     */
    public function title(?string $suffix = null): string
    {
        return Str::title($this->name) . $suffix;
    }

    /**
     * Get the factory name from table name.
     *
     * @return string The method returns the FactoryName
     *
     * @example echo (new Table('users'))->factory();
     * //=> User
     */
    public function factory(?string $suffix = null): string
    {
        return Str::studly($this->name) . 'Factory' . $suffix;
    }

    /**
     * Get the seeder name from table name.
     *
     * @return string The method returns the SeederName
     *
     * @example echo (new Table('users'))->seeder();
     * //=> User
     */
    public function seeder(?string $suffix = null): string
    {
        return Str::studly($this->name) . 'Seeder' . $suffix;
    }

    /**
     * Get the migration file name from table name.
     *
     * @return string The method returns the migration file name.
     *
     * @example echo (new Table('users'))->migration();
     * //=> 2024_03_18_135821_create_users_table.php
     */
    public function migration(): string
    {
        return date('Y_m_d_His') . '_create_' . $this->name . '_table.php';
    }

    /**
     * Let it know if the table has timestamps.
     */
    public function hasTimestamps(): bool
    {
        return ! (
            in_array('created_at', array_column($this->columns, 'field')) &&
            in_array('updated_at', array_column($this->columns, 'field'))
        );
    }

    /**
     * Get the primary key column.
     */
    public function getPrimaryColumn(): ?Column
    {
        foreach ($this->columns as $column) {
            if ($column->primaryKey) {
                return $column;
            }
        }

        return null;
    }

    /**
     * Class magic method to get the real table name.
     *
     * @return string The method returns the real table name.
     *
     * @example echo new Table('users');
     * //=> users
     */
    public function __toString(): string
    {
        return $this->name;
    }
}
